#include "IntelligentParser.hpp"

libIntelligentParser::libIntelligentParser()
{
}

libIntelligentParser::~libIntelligentParser()
{
    if (nullptr != input_video_codecpar)
    {
        avcodec_parameters_free(&input_video_codecpar);
    }
    if (nullptr != input_audio_codecpar)
    {
        avcodec_parameters_free(&input_audio_codecpar);
    }
    if (nullptr != v264_codecpar)
    {
        avcodec_parameters_free(&v264_codecpar);
    }
    if (nullptr != v265_codecpar)
    {
        avcodec_parameters_free(&v265_codecpar);
    }
    if (nullptr != aac_codecpar)
    {
        avcodec_parameters_free(&aac_codecpar);
    }
}

int libIntelligentParser::ReadConfig(string _config_filename)
{
    int ret = CI.ReadConfigInit(_config_filename);
    if (0 != ret)
    {
        PrintLog("Failed ReadConfigInit. INDEX_3089");
        return -1;
    }
    return 0;
}

int libIntelligentParser::SetParamFromAVFormatContext(AVFormatContext * _input_ctx)
{
    AVFormatContext *fc_local{ NULL };
    fc_local = _input_ctx; // 注意传递问题
    int ret;
    //
    for (int i = 0; i < fc_local->nb_streams; i++)
    {
        switch (fc_local->streams[i]->codecpar->codec_type)
        {
        case AVMEDIA_TYPE_VIDEO:
            input_video_stream_index = fc_local->streams[i]->index;
            input_stream_numbers++;
            input_video_stream_timebase = fc_local->streams[i]->time_base;
            input_videostream_rate = fc_local->streams[i]->r_frame_rate; //这里注意一下 输入源盒子的可靠性非常糟糕
            input_video_codecpar = avcodec_parameters_alloc();
            if (input_video_codecpar != NULL)
            {
                ret = avcodec_parameters_copy(input_video_codecpar, fc_local->streams[i]->codecpar); //留意一下 指针new出新的结构体后是否在外面有指向 重点是版本是否能正常对齐
                if (ret < 0)
                {
                    PrintLog("Failed video avcodec_parameters_copy INDEX_7");
                    return -1;
                }
            }
            break;
        case AVMEDIA_TYPE_AUDIO:
            input_audio_stream_index = fc_local->streams[i]->index;
            input_stream_numbers++;
            input_audio_stream_timebase = fc_local->streams[i]->time_base;
            input_audio_codecpar = avcodec_parameters_alloc();
            if (input_audio_codecpar != NULL)
            {
                ret = avcodec_parameters_copy(input_audio_codecpar, fc_local->streams[i]->codecpar);
                if (ret < 0)
                {
                    PrintLog("Failed audio avcodec_parameters_copy INDEX_8");
                    return -1;
                }
            }
            break;
        default:
            break;
        }
    }
    ////////////////////////////////////////////////////////////////////////// Encodec 参数亟需调整  编码出来的画质太渣了  码率也与设定的不一样
    //video 264
    if (CI.OUT_264URL.length())
    {
        v264_codecpar = avcodec_parameters_alloc();
        v264_codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
        v264_codecpar->codec_id = AV_CODEC_ID_H264;
        //    AT.par_h264->codec_tag = ;
        v264_codecpar->format = input_video_codecpar->format;

        v264_codecpar->bit_rate = CI.Bit_Rate_H264 * 1000;
        v264_codecpar->profile = input_video_codecpar->profile; //FF_PROFILE_H264_MAIN
                                                         //        v264_codecpar->profile = FF_PROFILE_H264_MAIN; //改为手动设置

        v264_codecpar->level = input_video_codecpar->level; //这里是否需要额外设置level  profile手动设置后是对编码器进行设置的，level这玩意儿是自动生成还是必须手动

        v264_codecpar->width = input_video_codecpar->width;
        v264_codecpar->height = input_video_codecpar->height;
        v264_codecpar->sample_aspect_ratio = input_video_codecpar->sample_aspect_ratio;
        v264_codecpar->field_order = input_video_codecpar->field_order;
        v264_codecpar->color_range = input_video_codecpar->color_range;
        v264_codecpar->color_primaries = input_video_codecpar->color_primaries;
        v264_codecpar->color_trc = input_video_codecpar->color_trc;
        v264_codecpar->color_space = input_video_codecpar->color_space;
        v264_codecpar->video_delay = input_video_codecpar->video_delay;
    }
    //video 265
    if (CI.OUT_265URL.length())
    {
        v265_codecpar = avcodec_parameters_alloc();
        v265_codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
        v265_codecpar->codec_id = AV_CODEC_ID_H265;

        v265_codecpar->format = input_video_codecpar->format;

        v265_codecpar->bit_rate = CI.Bit_Rate_H265 * 1000;
        v265_codecpar->profile = FF_PROFILE_HEVC_MAIN;
        //        v265_codecpar->profile = in_v_codecpar->profile; //FF_PROFILE_HEVC_MAIN FF_PROFILE_HEVC_REXT
        v265_codecpar->level = FF_LEVEL_UNKNOWN;
        //        v265_codecpar->level = in_v_codecpar->level; //这里是否需要额外设置level  profile手动设置后是对编码器进行设置的，level这玩意儿是自动生成还是必须手动

        v265_codecpar->width = input_video_codecpar->width;
        v265_codecpar->height = input_video_codecpar->height;
        v265_codecpar->sample_aspect_ratio = input_video_codecpar->sample_aspect_ratio;
        v265_codecpar->field_order = input_video_codecpar->field_order;
        v265_codecpar->color_range = input_video_codecpar->color_range;
        v265_codecpar->color_primaries = input_video_codecpar->color_primaries;
        v265_codecpar->color_trc = input_video_codecpar->color_trc;
        v265_codecpar->color_space = input_video_codecpar->color_space;
        v265_codecpar->video_delay = input_video_codecpar->video_delay;
    }
    //audio aac
    if (input_audio_codecpar->channels) //至少得有一路声道吧 现在是有无声道的可能性的
    {
        aac_codecpar = avcodec_parameters_alloc();
        aac_codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
        aac_codecpar->codec_id = AV_CODEC_ID_AAC;
        //    aac_codecpar->codec_tag = MKTAG('H', '2', '6', '4');
        aac_codecpar->format = input_audio_codecpar->format;
        //        aac_codecpar->profile = FF_PROFILE_AAC_MAIN;//FF_PROFILE_AAC_MAIN  进一步待验
        aac_codecpar->profile = input_audio_codecpar->profile;

        aac_codecpar->bit_rate = input_audio_codecpar->bit_rate;
        aac_codecpar->bits_per_coded_sample = input_audio_codecpar->bits_per_coded_sample;
        aac_codecpar->bits_per_raw_sample = input_audio_codecpar->bits_per_raw_sample;
        aac_codecpar->channel_layout = input_audio_codecpar->channel_layout;
        aac_codecpar->channels = input_audio_codecpar->channels;
        aac_codecpar->sample_rate = input_audio_codecpar->sample_rate;
        aac_codecpar->block_align = input_audio_codecpar->block_align;
        aac_codecpar->frame_size = input_audio_codecpar->frame_size;
        aac_codecpar->initial_padding = input_audio_codecpar->initial_padding;
        aac_codecpar->trailing_padding = input_audio_codecpar->trailing_padding;
        aac_codecpar->seek_preroll = input_audio_codecpar->seek_preroll;
    }
    ////////////////////////////////////////////////////////// Init Parser
    PS.PI.BufferMaxTime = CI.BufferMaxTime;
    PS.PI.Caption = CI.Caption;
    PS.PI.Border = CI.Border;
    PS.PI.WIDTH_DEN = CI.WIDTH_DEN;
    PS.PI.HEIGHT_DEN = CI.HEIGHT_DEN;
    PS.PI.Sampling = CI.Sampling;

    PS.PI.width = input_video_codecpar->width;
    PS.PI.height = input_video_codecpar->height;

    PS.PI.rec_pi = Rect(0, PS.PI.Caption, PS.PI.width, PS.PI.height - PS.PI.Caption - PS.PI.Border);

    PS.PI.BaseColor1_RGB[0] = CI.BaseColor1_RGB[0];
    PS.PI.BaseColor1_RGB[1] = CI.BaseColor1_RGB[1];
    PS.PI.BaseColor1_RGB[2] = CI.BaseColor1_RGB[2];

    PS.PI.max_rect_width = PS.PI.width / PS.PI.WIDTH_DEN;
    PS.PI.max_rect_height = PS.PI.height / PS.PI.HEIGHT_DEN;
    PS.PI.max_rect_siz = PS.PI.max_rect_width * PS.PI.max_rect_height;

    Size s_size{ PS.PI.width, PS.PI.height };
    int picture_size = av_image_get_buffer_size(AV_PIX_FMT_BGR24, PS.PI.width, PS.PI.height, 1);
    ret = PS.pbuffer.InitParserBuffer(s_size, AV_PIX_FMT_BGR24, (AVPixelFormat)input_video_codecpar->format);
    if (ret<0)
    {
        WriteLog("Failed  PS.pbuffer.InitParserBuffer. INDEX_1990");
        return -1;
    }
    ret = PS.InitParser();//!
    if (ret<0)
    {
        WriteLog("Failed  PS.InitParser(). INDEX_1991");
        return -1;
    }
    PS.src_blend.create(Size(PS.PI.width, PS.PI.height), CV_8UC3); //用不上？
                                                                   //buffer
    sws_format2bgr.Init(input_video_codecpar->width, input_video_codecpar->height, (AVPixelFormat)input_video_codecpar->format, input_video_codecpar->width, input_video_codecpar->height, AV_PIX_FMT_BGR24);
    sws_bgr2format.Init(input_video_codecpar->width, input_video_codecpar->height, AV_PIX_FMT_BGR24, input_video_codecpar->width, input_video_codecpar->height, (AVPixelFormat)input_video_codecpar->format);
    ////////////////////////////////////////////////////////////////////////// 内存
    //video buffer
    video_fifo.framepp_number = (input_videostream_rate.num / input_videostream_rate.den)*CI.BufferMaxTime;
    video_fifo.framepp = new AVFramePP[video_fifo.framepp_number];

    video_fifo.read_index = video_fifo.write_index = 0;
    video_fifo.read_number = 0;
    video_fifo.write_number = video_fifo.framepp_number;
    //audio buffer
    audio_fifo.framepp_number = CI.BufferMaxTime*(input_audio_codecpar->sample_rate / input_audio_codecpar->frame_size) * 2; //预留一倍，兼容video的buffer
    audio_fifo.framepp = new AVFramePP[audio_fifo.framepp_number];

    audio_fifo.read_index = audio_fifo.write_index = 0;
    audio_fifo.read_number = 0;
    audio_fifo.write_number = audio_fifo.framepp_number;
    //
    fc_local = NULL;
    return 0;
}

int libIntelligentParser::InitGlobalBuffer(string _config_filename)
{
    int ret = CI.ReadConfigInit(_config_filename);
    if (0 != ret)
    {
        PrintLog("Failed ReadConfigInit. INDEX_30");
        return -1;
    }

    AVFormatContext *ic{ nullptr };
    ic = avformat_alloc_context();
    if (!ic)
    {
        PrintLog("Failed avformat_alloc_context. INDEX_31");
        avformat_free_context(ic);
        return -1;
    }
    ret = avformat_open_input(&ic, CI.IN_URL.c_str(), /*ifmt*/NULL, /*&options*/NULL); //有问题，断流的时候返回值是0 不正常
    while (0 != ret)     //在这里循环拉取链接
    {
        Sleep(6000);
        ret = avformat_open_input(&ic, CI.IN_URL.c_str(), /*ifmt*/NULL, /*&options*/NULL);
    }
    if (avformat_find_stream_info(ic, NULL) < 0)
    {
        PrintLog("Could not read stream information .INDEX_4");
        avformat_flush(ic);  //??
        avformat_close_input(&ic);
        return -1;
    }
    //
    for (int i = 0; i < ic->nb_streams; i++)
    {
        switch (ic->streams[i]->codecpar->codec_type)
        {
        case AVMEDIA_TYPE_VIDEO:
            input_video_stream_index = ic->streams[i]->index;
            input_stream_numbers++;
            input_video_stream_timebase = ic->streams[i]->time_base;
            input_videostream_rate = ic->streams[i]->r_frame_rate; //盒子的可靠性基本没有  一般输出的都是实际的两倍帧率  先当输入稳定且正常
            input_video_codecpar = avcodec_parameters_alloc();
            if (input_video_codecpar != NULL)
            {
                ret = avcodec_parameters_copy(input_video_codecpar, ic->streams[i]->codecpar); //留意一下 指针new出新的结构体后是否在外面有指向 重点是版本是否能正常对齐
                if (ret < 0)
                {
                    PrintLog("Failed video avcodec_parameters_copy INDEX_7");
                    return -1;
                }
            }
            break;
        case AVMEDIA_TYPE_AUDIO:
            input_audio_stream_index = ic->streams[i]->index;
            input_stream_numbers++;
            input_audio_stream_timebase = ic->streams[i]->time_base;
            input_audio_codecpar = avcodec_parameters_alloc();
            if (input_audio_codecpar != NULL)
            {
                ret = avcodec_parameters_copy(input_audio_codecpar, ic->streams[i]->codecpar);
                if (ret < 0)
                {
                    PrintLog("Failed audio avcodec_parameters_copy INDEX_8");
                    return -1;
                }
            }
            break;
        default:
            break;
        }
    }
    ////////////////////////////////////////////////////////////////////////// Encodec 参数亟需调整  编码出来的画质太渣了  码率也与设定的不一样
    //video 264
    if (CI.OUT_264URL.length())
    {
        v264_codecpar = avcodec_parameters_alloc();
        v264_codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
        v264_codecpar->codec_id = AV_CODEC_ID_H264;
        //    AT.par_h264->codec_tag = ;
        v264_codecpar->format = input_video_codecpar->format;

        v264_codecpar->bit_rate = CI.Bit_Rate_H264 * 1000;
        v264_codecpar->profile = input_video_codecpar->profile; //FF_PROFILE_H264_MAIN
//        v264_codecpar->profile = FF_PROFILE_H264_MAIN; //改为手动设置

        v264_codecpar->level = input_video_codecpar->level; //这里是否需要额外设置level  profile手动设置后是对编码器进行设置的，level这玩意儿是自动生成还是必须手动

        v264_codecpar->width = input_video_codecpar->width;
        v264_codecpar->height = input_video_codecpar->height;
        v264_codecpar->sample_aspect_ratio = input_video_codecpar->sample_aspect_ratio;
        v264_codecpar->field_order = input_video_codecpar->field_order;
        v264_codecpar->color_range = input_video_codecpar->color_range;
        v264_codecpar->color_primaries = input_video_codecpar->color_primaries;
        v264_codecpar->color_trc = input_video_codecpar->color_trc;
        v264_codecpar->color_space = input_video_codecpar->color_space;
        v264_codecpar->video_delay = input_video_codecpar->video_delay;
    }
    //video 265
    if (CI.OUT_265URL.length())
    {
        v265_codecpar = avcodec_parameters_alloc();
        v265_codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
        v265_codecpar->codec_id = AV_CODEC_ID_H265;

        v265_codecpar->format = input_video_codecpar->format;

        v265_codecpar->bit_rate = CI.Bit_Rate_H265 * 1000;
        v265_codecpar->profile = FF_PROFILE_HEVC_MAIN;
//        v265_codecpar->profile = in_v_codecpar->profile; //FF_PROFILE_HEVC_MAIN FF_PROFILE_HEVC_REXT
        v265_codecpar->level = FF_LEVEL_UNKNOWN;
//        v265_codecpar->level = in_v_codecpar->level; //这里是否需要额外设置level  profile手动设置后是对编码器进行设置的，level这玩意儿是自动生成还是必须手动

        v265_codecpar->width = input_video_codecpar->width;
        v265_codecpar->height = input_video_codecpar->height;
        v265_codecpar->sample_aspect_ratio = input_video_codecpar->sample_aspect_ratio;
        v265_codecpar->field_order = input_video_codecpar->field_order;
        v265_codecpar->color_range = input_video_codecpar->color_range;
        v265_codecpar->color_primaries = input_video_codecpar->color_primaries;
        v265_codecpar->color_trc = input_video_codecpar->color_trc;
        v265_codecpar->color_space = input_video_codecpar->color_space;
        v265_codecpar->video_delay = input_video_codecpar->video_delay;
    }
    //audio aac
    if (input_audio_codecpar->channels) //至少得有一路声道吧 现在是有无声道的可能性的
    {
        aac_codecpar = avcodec_parameters_alloc();
        aac_codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
        aac_codecpar->codec_id = AV_CODEC_ID_AAC;
        //    aac_codecpar->codec_tag = MKTAG('H', '2', '6', '4');
        aac_codecpar->format = input_audio_codecpar->format; 
//        aac_codecpar->profile = FF_PROFILE_AAC_MAIN;//FF_PROFILE_AAC_MAIN  进一步待验
        aac_codecpar->profile = input_audio_codecpar->profile;

        aac_codecpar->bit_rate = input_audio_codecpar->bit_rate;
        aac_codecpar->bits_per_coded_sample = input_audio_codecpar->bits_per_coded_sample;
        aac_codecpar->bits_per_raw_sample = input_audio_codecpar->bits_per_raw_sample;
        aac_codecpar->channel_layout = input_audio_codecpar->channel_layout;
        aac_codecpar->channels = input_audio_codecpar->channels;
        aac_codecpar->sample_rate = input_audio_codecpar->sample_rate;
        aac_codecpar->block_align = input_audio_codecpar->block_align;
        aac_codecpar->frame_size = input_audio_codecpar->frame_size;
        aac_codecpar->initial_padding = input_audio_codecpar->initial_padding;
        aac_codecpar->trailing_padding = input_audio_codecpar->trailing_padding;
        aac_codecpar->seek_preroll = input_audio_codecpar->seek_preroll;
    }
    ////////////////////////////////////////////////////////// Init Parser
    PS.PI.BufferMaxTime = CI.BufferMaxTime;
    PS.PI.Caption = CI.Caption;
    PS.PI.Border = CI.Border;
    PS.PI.WIDTH_DEN = CI.WIDTH_DEN;
    PS.PI.HEIGHT_DEN = CI.HEIGHT_DEN;
    PS.PI.Sampling = CI.Sampling;

    PS.PI.width = input_video_codecpar->width;
    PS.PI.height = input_video_codecpar->height;

    PS.PI.rec_pi = Rect(0, PS.PI.Caption, PS.PI.width, PS.PI.height - PS.PI.Caption - PS.PI.Border);

    PS.PI.BaseColor1_RGB[0] = CI.BaseColor1_RGB[0];
    PS.PI.BaseColor1_RGB[1] = CI.BaseColor1_RGB[1];
    PS.PI.BaseColor1_RGB[2] = CI.BaseColor1_RGB[2];

    PS.PI.max_rect_width = PS.PI.width / PS.PI.WIDTH_DEN;
    PS.PI.max_rect_height = PS.PI.height / PS.PI.HEIGHT_DEN;
    PS.PI.max_rect_siz = PS.PI.max_rect_width * PS.PI.max_rect_height;

    Size s_size{ PS.PI.width, PS.PI.height };
    int picture_size = av_image_get_buffer_size(AV_PIX_FMT_BGR24, PS.PI.width, PS.PI.height,1);
    ret = PS.pbuffer.InitParserBuffer(s_size, AV_PIX_FMT_BGR24, (AVPixelFormat)input_video_codecpar->format);
    if (ret<0)
    {
        WriteLog("Failed  PS.pbuffer.InitParserBuffer. INDEX_1990");
        return -1;
    }    
    ret = PS.InitParser();//!
    if (ret<0)
    {
        WriteLog("Failed  PS.InitParser(). INDEX_1991");
        return -1;
    }
    PS.src_blend.create(Size(PS.PI.width, PS.PI.height), CV_8UC3); //用不上？
    //buffer
    sws_format2bgr.Init(input_video_codecpar->width, input_video_codecpar->height, (AVPixelFormat)input_video_codecpar->format, input_video_codecpar->width, input_video_codecpar->height, AV_PIX_FMT_BGR24);
    sws_bgr2format.Init(input_video_codecpar->width, input_video_codecpar->height, AV_PIX_FMT_BGR24, input_video_codecpar->width, input_video_codecpar->height, (AVPixelFormat)input_video_codecpar->format);
    ////////////////////////////////////////////////////////////////////////// 内存
    //video buffer
    video_fifo.framepp_number = (input_videostream_rate.num / input_videostream_rate.den)*CI.BufferMaxTime;
    video_fifo.framepp = new AVFramePP[video_fifo.framepp_number];

    video_fifo.read_index = video_fifo.write_index = 0;
    video_fifo.read_number = 0;
    video_fifo.write_number = video_fifo.framepp_number;
    //audio buffer
    audio_fifo.framepp_number = CI.BufferMaxTime*(input_audio_codecpar->sample_rate / input_audio_codecpar->frame_size) * 2; //预留一倍，兼容video的buffer
    audio_fifo.framepp = new AVFramePP[audio_fifo.framepp_number];

    audio_fifo.read_index = audio_fifo.write_index = 0;
    audio_fifo.read_number = 0;
    audio_fifo.write_number = audio_fifo.framepp_number;
    //
    avformat_flush(ic);  //
    avformat_close_input(&ic);
    return 0;
}

int libIntelligentParser::WriteVideoFrame(AVFrame *_frame)
{
    video_fifo.m.lock();
    if (video_fifo.write_number == 0)
    {
        WriteLog("Video fifo full! INDEX_12221");
        video_fifo.m.unlock();
        return -1; //
    }
    if (NULL == _frame || _frame->data == NULL)
    {
        PrintLog("frame is empty! INDEX_1321");
        video_fifo.m.unlock();
        return -1; //
    }
    //
    if (video_fifo.framepp[video_fifo.write_index].Copy(_frame) != 0)
    {
        PrintLog("Failed Copy. INDEX_6655");
        video_fifo.m.unlock();
        return -1;
    }
    video_fifo.current_index++;
    video_fifo.framepp[video_fifo.write_index].frame_index = video_fifo.current_index;
    video_fifo.framepp[video_fifo.write_index].frame->pts = _frame->pkt_pts;
    //
    video_fifo.write_index++;
    if (video_fifo.write_index == video_fifo.framepp_number)
    {
        video_fifo.write_index = 0;
    }
    video_fifo.write_number--;
    video_fifo.read_number++;
    //在这里写入识别模块的内部缓存
    if (parser_sampling == CI.Sampling)
    {
        if (PS.pbuffer.AddFrame(_frame, video_fifo.current_index)<0)
        {
            PrintLog("Failed PS.pbuffer.AddFrame. INDEX_1234");
            video_fifo.m.unlock();
            return -1;
        }
        parser_sampling = 0;
    }
    parser_sampling++;  //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!测试
    //
    video_fifo.m.unlock();
    return 0;
}

int libIntelligentParser::WriteAudioFrame(AVFrame *_frame)
{
    audio_fifo.m.lock();
    if (audio_fifo.write_number == 0)
    {
        WriteLog("Audio fifo full! INDEX_22221");
        audio_fifo.m.unlock();
        return -1; //
    }
    if (NULL == _frame || _frame->data == NULL)
    {
        PrintLog("frame is empty! INDEX_1321");
        audio_fifo.m.unlock();
        return -1; //
    }
    //
    if (audio_fifo.framepp[audio_fifo.write_index].Copy(_frame) != 0)
    {
        PrintLog("Failed Copy. INDEX_6656");
        audio_fifo.m.unlock();
        return -1;
    }
    audio_fifo.current_index++;
    audio_fifo.framepp[audio_fifo.write_index].frame_index = audio_fifo.current_index;
    audio_fifo.framepp[audio_fifo.write_index].frame->pts = _frame->pkt_pts;
    //
    audio_fifo.write_index++;
    if (audio_fifo.write_index == audio_fifo.framepp_number)
    {
        audio_fifo.write_index = 0;
    }
    audio_fifo.write_number--;
    audio_fifo.read_number++;
    //
    audio_fifo.m.unlock();
    return 0;
}

int libIntelligentParser::ReadVideoFrame(AVFrame *_frame, int64_t &_frame_index)
{
    video_fifo.m.lock();
    if (video_fifo.read_number == 0)
    {
        PrintLog("Video fifo empty! INDEX_32221");
        video_fifo.m.unlock();
        return -1; //
    }
    if (NULL == _frame || _frame->data == NULL)
    {
        PrintLog("frame is empty! INDEX_31321");
        video_fifo.m.unlock();
        return -1; //
    }
    // 预加工
    if (ProcessPicture(video_fifo.framepp[video_fifo.read_index].frame, video_fifo.framepp[video_fifo.read_index].frame_index) < 0)
    {
        PrintLog("Failed ProcessPicture. INDEX_234");
        return -1;
    }
    //
    _frame_index = video_fifo.framepp[video_fifo.read_index].frame_index;
    int ret = av_frame_copy(_frame, video_fifo.framepp[video_fifo.read_index].frame);
    if (ret < 0)
    {
        PrintLog("Failed av_frame_copy! INDEX_33321");
        video_fifo.m.unlock();
        return -1; //

    }
    _frame->pts = video_fifo.framepp[video_fifo.read_index].frame->pts;
    //
    video_fifo.read_index++;
    if (video_fifo.read_index == video_fifo.framepp_number)
    {
        video_fifo.read_index = 0;
    }

    video_fifo.write_number++;
    video_fifo.read_number--;
    //
    video_fifo.m.unlock();
    return 0;
}

int libIntelligentParser::ReadAudioFrame(AVFrame *_frame)
{
    audio_fifo.m.lock();
    if (audio_fifo.read_number == 0)
    {
        PrintLog("Audio fifo empty! INDEX_42221");
        audio_fifo.m.unlock();
        return -1; //
    }
    if (NULL == _frame || _frame->data == NULL)
    {
        PrintLog("frame is empty! INDEX_41321");
        audio_fifo.m.unlock();
        return -1; //
    }

    int ret = av_frame_copy(_frame, audio_fifo.framepp[audio_fifo.read_index].frame);
    if (ret < 0)
    {
        PrintLog("Failed av_frame_copy! INDEX_43321");
        audio_fifo.m.unlock();
        return -1; //
    }
    _frame->pts = audio_fifo.framepp[audio_fifo.read_index].frame->pts;
    //
    audio_fifo.read_index++;
    if (audio_fifo.read_index == audio_fifo.framepp_number)
    {
        audio_fifo.read_index = 0;
    }

    audio_fifo.write_number++;
    audio_fifo.read_number--;
    //
    audio_fifo.m.unlock();
    return 0;
}

int libIntelligentParser::ReadVideoFrame(AVFramePP & _framepp, int64_t & _frame_index)
{
    video_fifo.m.lock();
    if (video_fifo.read_number == 0)
    {
        PrintLog("Video fifo empty! INDEX_32221");
        video_fifo.m.unlock();
        return -1; //
    }
    // 预加工
    if (ProcessPicture(video_fifo.framepp[video_fifo.read_index].frame, video_fifo.framepp[video_fifo.read_index].frame_index) < 0)
    {
        PrintLog("Failed ProcessPicture. INDEX_234");
        return -1;
    }
    //
    _frame_index = video_fifo.framepp[video_fifo.read_index].frame_index;
    _framepp.Copy(video_fifo.framepp[video_fifo.read_index].frame);
    _framepp.frame->pts = video_fifo.framepp[video_fifo.read_index].frame->pts;
    //
    video_fifo.read_index++;
    if (video_fifo.read_index == video_fifo.framepp_number)
    {
        video_fifo.read_index = 0;
    }

    video_fifo.write_number++;
    video_fifo.read_number--;
    //
    video_fifo.m.unlock();
    return 0;
}

int libIntelligentParser::ReadAudioFrame(AVFramePP & _framepp)
{
    audio_fifo.m.lock();
    if (audio_fifo.read_number == 0)
    {
        PrintLog("Audio fifo empty! INDEX_42221");
        audio_fifo.m.unlock();
        return -1; //
    }
    _framepp.Copy(audio_fifo.framepp[audio_fifo.read_index].frame);
    _framepp.frame->pts = audio_fifo.framepp[audio_fifo.read_index].frame->pts;
    //
    audio_fifo.read_index++;
    if (audio_fifo.read_index == audio_fifo.framepp_number)
    {
        audio_fifo.read_index = 0;
    }

    audio_fifo.write_number++;
    audio_fifo.read_number--;
    //
    audio_fifo.m.unlock();
    return 0;
}

int libIntelligentParser::GetVideoBufferPercent()
{
    int f_local = (video_fifo.read_number * 100) / video_fifo.framepp_number;
    //     MEMORYSTATUS ms;
    //     ::GlobalMemoryStatus(&ms);
    //     f_local = ms.dwAvailPhys;
    return f_local;
}

int libIntelligentParser::ProcessPicture(AVFrame * _frame, int64_t _index)
{
    ParserPack2 pp;
    DeleteParserPack(_index,pp);
    if (_frame == NULL || _frame->data == NULL)
    {
        PrintLog("Error: ProcessPicture frame is empty. INDEX_431");
        return -1;
    }
    if (pp.rec.size())
    {
        //if (pp.max_index<_index || pp.min_index>_index)
        //{
        //    cout << pp.max_index << "~" << pp.min_index << " : " << _index << endl;
        //}
        if ((pp.max_index > _index) && (pp.min_index < _index)) //范围之内 加工图片
        {
            AVFramePP frame_local;     
            int frame_local_buffersize = av_image_get_buffer_size(AV_PIX_FMT_BGR24, _frame->width, _frame->height, 1); //linesize里面3个2048··· 内存都被吃了  虽然还没有实际占用，但一旦本地缓存开始，内存就等着被吃干净···
            uint8_t *frame_local_buffer = new uint8_t[frame_local_buffersize];

            if (frame_local.InitSetFrame(AV_PIX_FMT_BGR24, _frame->width, _frame->height, frame_local_buffer, frame_local_buffersize) != 0)
            {
                PrintLog("Failed video InitSetFrame. INDEX_7221");
            }
            sws_format2bgr.sws_scalePP(_frame->data, _frame->linesize, 0, _frame->height, frame_local.frame->data, frame_local.frame->linesize);
            //这里对图像做打码处理
            Mat src(Size(frame_local.frame->width, frame_local.frame->height), CV_8UC3);
            src.data = frame_local.frame->data[0];
            src.step = frame_local.frame->linesize[0];
            //
            for (int i = 0; i < pp.rec.size(); i++)
            {
                Mat mask = src(pp.rec[i]).clone(); //roi zone
//                 Mat maskk = mask.clone();
                blur(mask, mask, Size(mask.cols, mask.rows), Size(1, 1));
                mask.copyTo(src(pp.rec[i]));
                //for (int w = 0; w < mask.cols; w++)
                //{
                //    uchar s = mask.at<uchar>(0, w * 3 + 0);
                //    uchar ss = mask.at<uchar>(0, w * 3 + 1);
                //    uchar sss = mask.at<uchar>(0, w * 3 + 2);
                //    for (int h{ 0 }; h < mask.rows; h++)
                //    {
                //        mask.at<uchar>(h, w * 3 + 0) = s;
                //        mask.at<uchar>(h, w * 3 + 1) = ss;
                //        mask.at<uchar>(h, w * 3 + 2) = sss;
                //    }
                //}
            }
            sws_bgr2format.sws_scalePP(frame_local.frame->data, frame_local.frame->linesize, 0, _frame->height, _frame->data, _frame->linesize);
            delete[] frame_local_buffer;
        }
    }
    return 0;
}

int libIntelligentParser::DeleteParserPack(int64_t _index, ParserPack2 &_dst_pp)
{
    PS.PP.m.lock();
    while (PS.PP.d_pp.size()) 
    {
        if (PS.PP.d_pp.begin()->max_index <= _index)
        {
            PS.PP.d_pp.pop_front();
            continue;
        }
        else
        {
            break;
        }
    }
    if (PS.PP.d_pp.size())
    {
        _dst_pp = *PS.PP.d_pp.begin();
    }
    PS.PP.m.unlock();
    return 0;
}

